﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Timers;
using System.Runtime.InteropServices;
using System.Threading;
using MoteurAudio;
using Guitar;
using Modele;

namespace Module
{
    /// <summary>
    /// Logique d'interaction pour Accordeur.xaml
    /// Note : Le Module est dépendant du système audio de l'application
    /// </summary>
    public partial class Accordeur : Grid
    {

        //Timer d'enregistrement
        System.Timers.Timer timerSave = new System.Timers.Timer(50);
        
        //Variable de l'accordeur
        public bool isActivated = false;
    
        public Accordeur()
        {
            InitializeComponent();
            timerSave.Elapsed += new ElapsedEventHandler(timer_DetectionNotes);
            timerSave.Enabled = true;
            timerSave.Stop();

        }

        /**************** ACCORDEUR ****************/

        // Timer de détection des notes
        private void timer_DetectionNotes(object sender, ElapsedEventArgs e)
        {

            try
            {
                if (SystemeAudio.channel[0] != null)
                {


                    float[] spectre = new float[SystemeAudio.SPECTRUMSIZE];
                    float frequenceDominante = 0;
                    float max;
                    int noteDominante = 0;
                    int count = 0;

                    SystemeAudio.resultat = SystemeAudio.channel[0].getSpectrum(spectre, SystemeAudio.SPECTRUMSIZE, 0, FMOD.DSP_FFT_WINDOW.TRIANGLE);
                    SystemeAudio.erreurInfos(SystemeAudio.resultat);

                    max = 0;

                    for (count = 0; count < SystemeAudio.SPECTRUMSIZE; count++)
                    {
                        if (spectre[count] > 0.01f && spectre[count] > max)
                        {
                            max = spectre[count];
                            SystemeAudio.bin = count;
                        }
                    }

                    frequenceDominante = (float)SystemeAudio.bin * SystemeAudio.BINSIZE;       /* Fréquence dominante  min */

                    noteDominante = 0;

                    for (count = 0; count < 120; count++)
                    {
                        if (frequenceDominante >= MoteurAudio.SystemeAudio.notefreq[count] && frequenceDominante < MoteurAudio.SystemeAudio.notefreq[count + 1])
                        {
                            // Note la plus proche
                            if (Math.Abs(frequenceDominante - MoteurAudio.SystemeAudio.notefreq[count]) < Math.Abs(frequenceDominante - MoteurAudio.SystemeAudio.notefreq[count + 1]))
                            {
                                noteDominante = count;
                            }
                            else
                            {
                                noteDominante = count + 1;
                            }
                            break;
                        }
                    }


                    // On vérifie que le thread à un droit d'accès sur WPF
                    labelAccordeur.Dispatcher.Invoke(
                      System.Windows.Threading.DispatcherPriority.Normal,
                      new Action(
                        delegate()
                        {

                            slider1.Maximum = MoteurAudio.SystemeAudio.notefreq[noteDominante] + 50;
                            slider1.Minimum = MoteurAudio.SystemeAudio.notefreq[noteDominante] - 50;
                            slider1.Value = frequenceDominante;
                            if (App.option.LangueNotationMusicale == Note.Langue.Fr)
                            {
                                labelNote.Content = MoteurAudio.SystemeAudio.noteFR[noteDominante];
                            }
                            else
                            {
                                labelNote.Content = MoteurAudio.SystemeAudio.note[noteDominante];
                            }

                            labelAccordeur.Content = "Frequence: " + frequenceDominante + " -> " +
                                (((float)SystemeAudio.bin + 20.99f) * SystemeAudio.BINSIZE);
                        }
                    ));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception levée dans Accordeur.cs :" + ex.Message);



            }


            if (SystemeAudio.systemAudio != null)
            {
                SystemeAudio.systemAudio.update();

            }



        }

        public void button_ActiverAccordeur_Click(object sender, RoutedEventArgs e)
        {

            Start();

        }


        public void Start()
        {
            try
            {
                if (!isActivated)
                {
                    isActivated = true;
                    timerSave.Start();
                   
                    /*
                        Création d'un son pour enregistrer dessu
                    */
                    SystemeAudio.exinfo.cbsize = Marshal.SizeOf(SystemeAudio.exinfo);
                    SystemeAudio.exinfo.numchannels = 1;
                    SystemeAudio.exinfo.format = FMOD.SOUND_FORMAT.PCM16;
                    SystemeAudio.exinfo.defaultfrequency = SystemeAudio.OUTPUTRATE;
                    SystemeAudio.exinfo.length = (uint)(SystemeAudio.exinfo.defaultfrequency * 2 * SystemeAudio.exinfo.numchannels * 5);
                    Console.WriteLine(" ERRERRUR : null2");
                    SystemeAudio.resultat = SystemeAudio.systemAudio.createSound((string)null, (FMOD.MODE._2D | FMOD.MODE.SOFTWARE | FMOD.MODE.LOOP_NORMAL | FMOD.MODE.OPENUSER), ref SystemeAudio.exinfo, ref SystemeAudio.sound[0]);
                   
                    SystemeAudio.erreurInfos(SystemeAudio.resultat);


                    /* Début de l'enregistrement*/
                    SystemeAudio.resultat = SystemeAudio.systemAudio.recordStart(SystemeAudio.selectedInterface, SystemeAudio.sound[0], true);
                    SystemeAudio.erreurInfos(SystemeAudio.resultat);

                    Thread.Sleep(150);      /* On laisse du temps pour l'enreistrement*/

                    SystemeAudio.resultat = SystemeAudio.systemAudio.playSound(FMOD.CHANNELINDEX.REUSE, SystemeAudio.sound[0], false, ref SystemeAudio.channel[0]);
                    SystemeAudio.erreurInfos(SystemeAudio.resultat);

                    /* On coupe le volume pour éviter le larsen */
                    SystemeAudio.resultat = SystemeAudio.channel[0].setVolume(0);
                    SystemeAudio.erreurInfos(SystemeAudio.resultat);

                }
                else
                {
                    isActivated = false;

                    SystemeAudio.systemAudio.recordStop(SystemeAudio.selectedInterface);
                    timerSave.Stop();
                    labelAccordeur.Content = "";
                    button_ActiverAccordeur.IsChecked = false;
                }

           }

           catch (Exception ex)
            {
                Console.WriteLine("[Exception] Dans Accordeur.cs (start())" + ex.Message);            
                button_ActiverAccordeur.IsChecked = false;
                MessageBox.Show("Pilote Audio non détecté");
            }
        }

        private void checkBox1_Checked(object sender, RoutedEventArgs e)
        {
            try
            {
                SystemeAudio.channel[0].setVolume(100);
            }
            catch (Exception ex)
            {
                Console.WriteLine("[Exception] Dans Accordeur.cs (checkBox1_Checked())" + ex.Message);
                
                MessageBox.Show("Pilote Audio non détecté");
            }


        }

        private void checkBox1_Unchecked(object sender, RoutedEventArgs e)
        {
            try
            {
                SystemeAudio.channel[0].setVolume(0);
            }
            catch (Exception ex)
            {
                Console.WriteLine("[Exception] Dans Accordeur.cs (checkBox1_unChecked())" + ex.Message);

                MessageBox.Show("Pilote Audio non détecté");
            }
        }
    }
}
